/*=======================================================================================================================================
# ENB 0.313 CODE-LIX
BestArt Modding

=======================================================================================================================================*/

/*=======================================================================================================================================
	Downsampling Toggle - Set for Personal Convenience
=======================================================================================================================================*/

#define USE_DOWNSAMPLING			0


/*=======================================================================================================================================
	Example Resolutions, have to be set in drivers a/o any downsampling tool, and SkyrimPrefs.ini as well
=======================================================================================================================================*/

/**
		1.77777778 ratio
#define fWidth					1920.0
#define fHeight					1080.0
;
#define fWidth					2560.0
#define fHeight					1440.0
;
#define fWidth					2880.0
#define fHeight					1620.0
;
#define fWidth					3200.0
#define fHeight					1800.0
;
#define fWidth					3449.0
#define fHeight					1940.0
;
#define fWidth					3456.0
#define fHeight					1944.0
;
#define fWidth					3552.0
#define fHeight					1998.0
;
#define fWidth					3840.0
#define fHeight					2160.0
;
#define fWidth					4096.0
#define fHeight					2304.0
;
#define fWidth					4190.0
#define fHeight					2357.0
;
#define fWidth					5120.0
#define fHeight					2880.0
;
#define fWidth					5334.0
#define fHeight					3000.0

		1.6 ratio
#define fWidth					1920.0
#define fHeight					1200.0
;
#define fWidth					1680.0
#define fHeight					1050.0
;
#define fWidth					3840.0
#define fHeight					2400.0

		2.35 : 1 ratio
#define fWidth					2538.0
#define fHeight					1080.0
;
#define fWidth					2869.0
#define fHeight					1221.0
;
#define fWidth					3200.0
#define fHeight					1362.0
;
#define fWidth					3760.0
#define fHeight					1600.0
	
*/


/*=======================================================================================================================================
	Display Resolution - Enter your exact resolution scales below
=======================================================================================================================================*/

#if (USE_DOWNSAMPLING == 1)

#define fWidth					4190.0
#define fHeight					2357.0

#elif (USE_DOWNSAMPLING == 1)

#define fWidth					1920.0
#define fHeight					1080.0

#endif


/*=======================================================================================================================================
	Usefull Constants
=======================================================================================================================================*/

#define LUMA_CONST   float3(0.333, 0.333, 0.333)		// Luminance weight


/*=======================================================================================================================================
    Rec.601     float3( 0.299, 0.587, 0.114)
    Rec.709     float3( 0.2126, 0.7152, 0.0722)
=======================================================================================================================================*/

/*=======================================================================================================================================
	Internal Parameters
=======================================================================================================================================*/

#define ALF_SAMPLE   20

string  Param00 = "+++++ Starburst +++++";
float   Starburst_Intensity     <string UIName="Starburst_Intensity";       float UIMin=0;  > = {0.00};
float   Starburst_Curve         <string UIName="Starburst_Curve";           float UIMin=0;  > = {0.75};
float   Starburst_InnerEdge     <string UIName="Starburst_InnerEdge";       float UIMax=1;  > = {0.24};
float   Starburst_OuterEdge     <string UIName="Starburst_OuterEdge";       float UIMin=0;  > = {0.80};
float   Starburst_Scale = 0.2;

string  Param01 = "++++++ Flare1 ++++++";
float   Flare1_Scale            <string UIName="Flare5_Scale";                              > = {0.5};
float   Flare1_Ratio            <string UIName="Flare5_Ratio";              float UIMin=0;  > = {1};
float   Flare1_Intensity        <string UIName="Flare5_Intensity";          float UIMin=0;  > = {0};
float   Flare1_InnerEdge        <string UIName="Flare5_InnerEdge";          float UIMax=1;  > = {0.2};
float   Flare1_OuterEdge        <string UIName="Flare5_OuterEdge";          float UIMin=0;  > = {1};
float   Flare1_Distort_Curve    <string UIName="Flare5_Distort_Curve";      float UIMin=0;  > = {1};
float   Flare1_Distort_Scale    <string UIName="Flare5_Distort_Scale";      float UIMax=0;  > = {-1};
float3  Flare1_Tint             <string UIName="Flare5_Tint"; string UIWidget="color";      > = {1, 1, 1};
#define FLARE1_TEXTURE          SamplerBloom2

string  Param02 = "++++++ Flare2 ++++++";
float   Flare2_Scale            <string UIName="Flare2_Scale";                              > = {0.4};
float   Flare2_Ratio            <string UIName="Flare2_Ratio";              float UIMin=0;  > = {1};
float   Flare2_Intensity        <string UIName="Flare2_Intensity";          float UIMin=0;  > = {1};
float   Flare2_InnerEdge        <string UIName="Flare2_InnerEdge";          float UIMax=1;  > = {0};
float   Flare2_OuterEdge        <string UIName="Flare2_OuterEdge";          float UIMin=0;  > = {0.2};
float   Flare2_Distort_Curve    <string UIName="Flare2_Distort_Curve";      float UIMin=0;  > = {1};
float   Flare2_Distort_Scale    <string UIName="Flare2_Distort_Scale";      float UIMax=0;  > = {-0.2};
float3  Flare2_Tint             <string UIName="Flare2_Tint"; string UIWidget="color";      > = {1, 1, 1};
#define FLARE2_TEXTURE          SamplerBloom3

string  Param03 = "++++++ Flare3 ++++++";
float   Flare3_Scale            <string UIName="Flare3_Scale";                              > = {-1};
float   Flare3_Ratio            <string UIName="Flare3_Ratio";              float UIMin=0;  > = {1};
float   Flare3_Intensity        <string UIName="Flare3_Intensity";          float UIMin=0;  > = {1};
float   Flare3_InnerEdge        <string UIName="Flare3_InnerEdge";          float UIMax=1;  > = {0};
float   Flare3_OuterEdge        <string UIName="Flare3_OuterEdge";          float UIMin=0;  > = {0.2};
float   Flare3_Distort_Curve    <string UIName="Flare3_Distort_Curve";      float UIMin=0;  > = {1};
float   Flare3_Distort_Scale    <string UIName="Flare3_Distort_Scale";      float UIMax=0;  > = {-0.2};
float3  Flare3_Tint             <string UIName="Flare3_Tint"; string UIWidget="color";      > = {1, 1, 1};
#define FLARE3_TEXTURE          SamplerBloom3

string  Param04 = "++++++ Flare4 ++++++";
float   Flare4_Scale            <string UIName="Flare4_Scale";                              > = {-1.6};
float   Flare4_Ratio            <string UIName="Flare4_Ratio";              float UIMin=0;  > = {1};
float   Flare4_Intensity        <string UIName="Flare4_Intensity";          float UIMin=0;  > = {1};
float   Flare4_InnerEdge        <string UIName="Flare4_InnerEdge";          float UIMax=1;  > = {0.4};
float   Flare4_OuterEdge        <string UIName="Flare4_OuterEdge";          float UIMin=0;  > = {1};
float   Flare4_Distort_Curve    <string UIName="Flare4_Distort_Curve";      float UIMin=0;  > = {1};
float   Flare4_Distort_Scale    <string UIName="Flare4_Distort_Scale";      float UIMax=0;  > = {-1};
float3  Flare4_Tint             <string UIName="Flare4_Tint"; string UIWidget="color";      > = {1, 1, 1};
#define FLARE4_TEXTURE          SamplerBloom3

string  Param05 = "++++++ Flare5 ++++++";
float   Flare5_Scale            <string UIName="Flare5_Scale";                              > = {0.5};
float   Flare5_Ratio            <string UIName="Flare5_Ratio";              float UIMin=0;  > = {1};
float   Flare5_Intensity        <string UIName="Flare5_Intensity";          float UIMin=0;  > = {2};
float   Flare5_InnerEdge        <string UIName="Flare5_InnerEdge";          float UIMax=1;  > = {0.2};
float   Flare5_OuterEdge        <string UIName="Flare5_OuterEdge";          float UIMin=0;  > = {1};
float   Flare5_Distort_Curve    <string UIName="Flare5_Distort_Curve";      float UIMin=0;  > = {1};
float   Flare5_Distort_Scale    <string UIName="Flare5_Distort_Scale";      float UIMax=0;  > = {-1};
float3  Flare5_Tint             <string UIName="Flare5_Tint"; string UIWidget="color";      > = {1, 1, 1};
#define FLARE5_TEXTURE          SamplerBloom3

string  Param06 = "+++++++ ALF +++++++";
float   ALF_Width               <string UIName="ALF_Width"; float UIMax=0.2;float UIMin=0;  > = {0.08};
float   ALF_Curve               <string UIName="ALF_Curve";                 float UIMin=0;  > = {1};
float   ALF_Secondary           <string UIName="ALF_Secondary";             float UIMin=0;  > = {0.25};
float   ALF_Intensity           <string UIName="ALF_Intensity";             float UIMin=0;  > = {0.95};
float3  ALF_Tint                <string UIName="ALF_Tint"; string UIWidget="color";         > = {0.25, 0.25, 1};

string  Param07 = "++++++ Chroma ++++++";
float   Chroma_Scale            <string UIName="Chroma_Scale"; float UIStep = 0.001; float UIMin=0; > = {0.005};
float   Chroma_Curve            <string UIName="Chroma_Curve";                       float UIMin=0; > = {1};


/*=======================================================================================================================================
	External Parameters
=======================================================================================================================================*/

// Keyboard controlled temporary variables (in some versions exists in the config file). 
// Press and hold key 1,2,3...8 together with PageUp or PageDown to modify. By default all set to 1.0
float4  tempF1;         // 1,2,3,4
float4  tempF2;         // 5,6,7,8
float4  tempF3;         // 9,0
float4  ScreenSize;     // x=Width, y=1/Width, z=ScreenScaleY, w=1/ScreenScaleY
// Kyo, prod80 : these below will automatically index resolution-based effects on actual current screen resolution 
// #define fWidth  float( ScreenSize.x )					// Width
// #define fHeight float( ScreenSize.x * ScreenSize.w )				// Width * ( 1 / ( Width / Height ))
float   ENightDayFactor;// Changes in range 0..1, 0 means that night time, 1 - day time
float   EInteriorFactor;// Changes 0 or 1. 0 means that exterior, 1 - interior
float4  Timer;          // x=generic timer in range 0..1, period of 16777216 ms (4.6 hours), w=frame time elapsed (in seconds)
float4  TempParameters; // Additional info for computations
float4  LensParameters; // x=reflection intensity, y=reflection power, z=dirt intensity, w=dirt power
float   FieldOfView;    // Fov in degrees
float4  WeatherAndTime; // .x - current weather index, .y - outgoing weather index, .z - weather transition, .w - time of the day in 24 standart hours.


/*=======================================================================================================================================
	Textures a/ Samplers
=======================================================================================================================================*/

texture2D texColor;     // Output of Draw
texture2D texMask;      // Enblensmask texture
texture2D texBloom1;    // Original ENB blurred input;fullres, output of bloom prepass
texture2D texBloom2;    // Downsampled to 512
texture2D texBloom3;    // Downsampled to 256
texture2D texBloom4;    // Downsampled to 128
texture2D texBloom5;    // Downsampled to 64
texture2D texBloom6;    // Downsampled to 32
texture2D texBloom7;    // Empty
texture2D texBloom8;    // Empty

sampler2D SamplerColor = sampler_state
{
    Texture   = <texColor>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = NONE;
    AddressU  = Clamp;
    AddressV  = Clamp;
    SRGBTexture=FALSE;
    MaxMipLevel=0;
    MipMapLodBias=0;
};

sampler2D SamplerMask = sampler_state
{
    Texture   = <texMask>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = NONE;
    AddressU  = Clamp;
    AddressV  = Clamp;
    SRGBTexture=FALSE;
    MaxMipLevel=0;
    MipMapLodBias=0;
};

sampler2D SamplerBloom1 = sampler_state
{
    Texture   = <texBloom1>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = NONE;
    AddressU  = Clamp;
    AddressV  = Clamp;
    SRGBTexture=FALSE;
    MaxMipLevel=0;
    MipMapLodBias=0;
};

sampler2D SamplerBloom2 = sampler_state
{
    Texture   = <texBloom2>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = NONE;
    AddressU  = Clamp;
    AddressV  = Clamp;
    SRGBTexture=FALSE;
    MaxMipLevel=0;
    MipMapLodBias=0;
};

sampler2D SamplerBloom3 = sampler_state
{
    Texture   = <texBloom3>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = NONE;
    AddressU  = Clamp;
    AddressV  = Clamp;
    SRGBTexture=FALSE;
    MaxMipLevel=0;
    MipMapLodBias=0;
};

sampler2D SamplerBloom4 = sampler_state
{
    Texture   = <texBloom4>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = NONE;
    AddressU  = Clamp;
    AddressV  = Clamp;
    SRGBTexture=FALSE;
    MaxMipLevel=0;
    MipMapLodBias=0;
};

sampler2D SamplerBloom5 = sampler_state
{
    Texture   = <texBloom5>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = NONE;
    AddressU  = Clamp;
    AddressV  = Clamp;
    SRGBTexture=FALSE;
    MaxMipLevel=0;
    MipMapLodBias=0;
};

sampler2D SamplerBloom6 = sampler_state
{
    Texture   = <texBloom6>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = NONE;
    AddressU  = Clamp;
    AddressV  = Clamp;
    SRGBTexture=FALSE;
    MaxMipLevel=0;
    MipMapLodBias=0;
};

sampler2D SamplerBloom7 = sampler_state
{
    Texture   = <texBloom7>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = NONE;
    AddressU  = Clamp;
    AddressV  = Clamp;
    SRGBTexture=FALSE;
    MaxMipLevel=0;
    MipMapLodBias=0;
};

sampler2D SamplerBloom8 = sampler_state
{
    Texture   = <texBloom8>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = NONE;
    AddressU  = Clamp;
    AddressV  = Clamp;
    SRGBTexture=FALSE;
    MaxMipLevel=0;
    MipMapLodBias=0;
};


/*=======================================================================================================================================
	Structures
=======================================================================================================================================*/

struct VS_OUTPUT_POST
{
    float4 vpos     : POSITION;
    float2 txcoord0 : TEXCOORD0;
};
struct VS_INPUT_POST
{
    float3 pos      : POSITION;
    float2 txcoord0 : TEXCOORD0;
};


/*=======================================================================================================================================
	Functions
=======================================================================================================================================*/

float   Lum(float3 color)
{
    return dot(color, LUMA_CONST);
}

float2 Distort( float2 coord, float curve, float scale)
{
    float2 dist   = coord - 0.5;
    float  r      = length(float2( dist.x * ScreenSize.z, dist.y));
    float2 offset = pow( 2 * r, curve) * (dist / r) * scale;
    
    return coord + offset;
}

// temp.x == curve, .y == scale
float4 Chroma( sampler2D inputtex, float2 coord, float2 temp)
{
    float4 res = 0;
    res.r  = tex2D(inputtex, Distort(coord, temp.x, temp.y)).r;
    res.ga = tex2D(inputtex, coord).ga;
    res.b  = tex2D(inputtex, Distort(coord, temp.x, -temp.y)).b;
    return res;
}


/*=======================================================================================================================================
	Shaders
=======================================================================================================================================*/

// flare.x == scale, flare.y == ratio
VS_OUTPUT_POST VS_Draw(VS_INPUT_POST IN, uniform float2 flare)
{
    VS_OUTPUT_POST OUT;
    OUT.vpos        = float4(IN.pos.xyz, 1.0);
    OUT.vpos.xy    *= flare.x;
    OUT.vpos.x     *= flare.y;
    OUT.txcoord0.xy = IN.txcoord0.xy + TempParameters.xy;//1.0/(bloomtexsize*2.0)
    return OUT;
}

// ALF + Dirt, FullScreen, reduced res
float4 PS_Draw(VS_OUTPUT_POST IN) : COLOR
{
    float2 coord = IN.txcoord0;
    float4 res   = 0;
    
// Dirt Starts    
    float3 dirt   = tex2D(SamplerBloom6, coord).rgb;
    float3 mask   = tex2D(SamplerMask, coord).rgb;
    float  normal = max(dirt.x, max(dirt.y, dirt.z));
    normal = pow( normal / ( 1.0 + normal), LensParameters.w);
    res.rgb += mask * dirt * normal * LensParameters.z;
// Dirt Ends

// ALF Starts
    for(int i=0; i < ALF_SAMPLE; i++)
    {
        float2 offset = float2(i - (ALF_SAMPLE - 1) * 0.5, 0) * ALF_Width;
        offset+= coord;
        normal = (abs(offset.x - 0.5) > 0.5)? 0:1;
        res.a += pow(Lum(tex2D(SamplerBloom1, offset).rgb), ALF_Curve) * normal;
    }
    res.a /= ALF_SAMPLE;
// ALF ENDs
    
    return res;
}

// flare PS with distortion, center/edge vignette
// distortion.x == curve, .y == scale, .z == inner edge, .w == outer edge
float4 PS_Flare(VS_OUTPUT_POST IN, uniform sampler2D inputtex, uniform float4 tint, uniform float4 flare) : COLOR
{
    float2 coord = Distort(IN.txcoord0.xy, flare.x, flare.y);
    float4 res   = tex2D(inputtex, coord);
    res.a    = max( res.r, max( res.g, res.b));				// Normal weight
    res.a    = pow( res.a / ( 1.0 + res.a), LensParameters.y);
    coord    = IN.txcoord0.xy;
    coord   -= 0.5;
    coord.y *= ScreenSize.w;
    coord.y  = length(coord) * 2;
    res.rgb *= smoothstep(flare.z, 1, coord.y);//center vignette
    res.rgb *= 1 - smoothstep(0, flare.w, coord.y);//edge vignette
    res.rgb *= res.a * tint.rgb * LensParameters.x * tint.a;//intensity
    return res;
}
       
// Post Process, Chromatic; Starburst
float4  PS_PostProcess(VS_OUTPUT_POST IN) : COLOR
{
    float2 coord = IN.txcoord0.xy;
// Chromatic Aberration Starts
    float4 res   = Chroma(SamplerColor, coord, float2(Chroma_Curve, Chroma_Scale));
// Chromatic Aberration Ends
    
// Starburst Starts
    float alpha;
    float dist   = length((coord - 0.5) * float2(1, ScreenSize.w)) * 2;
    float weight = smoothstep(Starburst_InnerEdge, 1, dist);
    weight  *= 1 - smoothstep(0, Starburst_OuterEdge, dist);
    coord    = Distort(0.5 + (coord - 0.5) * Starburst_Scale, 0, 1);
    alpha    = Lum(tex2D(SamplerBloom1, coord).rgb);
    coord    = float2( coord.x - coord.y, coord.x + coord.y - 1) * 0.7071 + 0.5; //rotate 45 degree
    alpha   -= Lum(tex2D(SamplerBloom1, coord).rgb);
    res.rgb *= 1.0 + pow(abs(alpha), Starburst_Curve) * Starburst_Intensity * 1000 * weight;
// Starburst ENDs

// ALF Starts
    res.a = 0;
    coord = IN.txcoord0.xy;
    for(int i=0; i < ALF_SAMPLE; i++)
    {
        float2 offset = float2(i - (ALF_SAMPLE - 1) * 0.5, 0) * ALF_Width / ALF_SAMPLE;
        offset+= coord;
        weight = (abs(offset.x - 0.5) > 0.5)? 0:1;
        res.a += tex2D(SamplerColor, offset).a * weight;
        res.a += tex2D(SamplerColor, 1 - offset).a * ALF_Secondary * weight;
    }
    res.a /= ALF_SAMPLE;
    res.rgb += (tex2D(SamplerBloom4, coord).rgb + tex2D(SamplerBloom2, coord).rgb) * res.a * ALF_Tint * ALF_Intensity;
// ALF ENDs

    res.rgb  = max( min( res.rgb, 32768.0), 0.0);
    return res;
}


/*=======================================================================================================================================
	Passes Of Techniques
=======================================================================================================================================*/

technique Draw
{
    pass p0
    {
        VertexShader = compile vs_3_0 VS_Draw(float2(1, 1));
        PixelShader  = compile ps_3_0 PS_Draw();
        
        ColorWriteEnable=RED|GREEN|BLUE|ALPHA;
        DitherEnable=FALSE;
        ZEnable=FALSE;
        CullMode=NONE;
        ALPHATESTENABLE=FALSE;
        SEPARATEALPHABLENDENABLE=FALSE;
        StencilEnable=FALSE;
        FogEnable=FALSE;
        SRGBWRITEENABLE=FALSE;
    }

    pass p1
    {
        VertexShader = compile vs_3_0 VS_Draw(float2(Flare1_Scale, Flare1_Ratio));
        PixelShader  = compile ps_3_0 PS_Flare(FLARE1_TEXTURE, float4(Flare1_Tint, Flare1_Intensity), 
                        float4(Flare1_Distort_Curve, Flare1_Distort_Scale, Flare1_InnerEdge, Flare1_OuterEdge));

        AlphaBlendEnable=TRUE;
        SrcBlend=ONE;
        DestBlend=ONE;
        ColorWriteEnable=RED|GREEN|BLUE;//warning, no alpha output!
        DitherEnable=FALSE;
        ZEnable=FALSE;
        CullMode=NONE;
        ALPHATESTENABLE=FALSE;
        SEPARATEALPHABLENDENABLE=FALSE;
        StencilEnable=FALSE;
        FogEnable=FALSE;
        SRGBWRITEENABLE=FALSE;
    }
    pass p2
    {
        VertexShader = compile vs_3_0 VS_Draw(float2(Flare2_Scale, Flare2_Ratio));
        PixelShader  = compile ps_3_0 PS_Flare(FLARE2_TEXTURE, float4(Flare2_Tint, Flare2_Intensity), 
                        float4(Flare2_Distort_Curve, Flare2_Distort_Scale, Flare2_InnerEdge, Flare2_OuterEdge));
    }
    pass p3
    {
        VertexShader = compile vs_3_0 VS_Draw(float2(Flare3_Scale, Flare3_Ratio));
        PixelShader  = compile ps_3_0 PS_Flare(FLARE3_TEXTURE, float4(Flare3_Tint, Flare3_Intensity), 
                        float4(Flare3_Distort_Curve, Flare3_Distort_Scale, Flare3_InnerEdge, Flare3_OuterEdge));
    }
    pass p4
    {
        VertexShader = compile vs_3_0 VS_Draw(float2(Flare4_Scale, Flare4_Ratio));
        PixelShader  = compile ps_3_0 PS_Flare(FLARE4_TEXTURE, float4(Flare4_Tint, Flare4_Intensity), 
                        float4(Flare4_Distort_Curve, Flare4_Distort_Scale, Flare4_InnerEdge, Flare4_OuterEdge));
    }
    pass p5
    {
        VertexShader = compile vs_3_0 VS_Draw(float2(Flare5_Scale, Flare5_Ratio));
        PixelShader  = compile ps_3_0 PS_Flare(FLARE5_TEXTURE, float4(Flare5_Tint, Flare5_Intensity), 
                        float4(Flare5_Distort_Curve, Flare5_Distort_Scale, Flare5_InnerEdge, Flare5_OuterEdge));
    }
}

// Final pass, output to screen with additive blending and no alpha
technique LensPostPass
{
    pass p0
    {
        VertexShader = compile vs_3_0 VS_Draw(float2(1, 1));
        PixelShader  = compile ps_3_0 PS_PostProcess();

        AlphaBlendEnable=TRUE;
        SrcBlend=ONE;
        DestBlend=ONE;
        ColorWriteEnable=RED|GREEN|BLUE;//warning, no alpha output!
        DitherEnable=FALSE;
        ZEnable=FALSE;
        CullMode=NONE;
        ALPHATESTENABLE=FALSE;
        SEPARATEALPHABLENDENABLE=FALSE;
        StencilEnable=FALSE;
        FogEnable=FALSE;
        SRGBWRITEENABLE=FALSE;
    }
}